package com.hd.trans.share;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.Nullable;

import com.hd.trans.network.bean.DownloadInfo;
import com.hd.trans.network.component.DownLoadObserver;
import com.hd.trans.network.component.DownloadManager;
import com.hd.trans.network.component.FileTranslateCallback;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


public class UrlDownloadRequest {
    private final String TAG = "UrlDownloadThread";

    private String taskId;
    private List<String> urls;
    private List<String> filePaths;
    private DownloadArg downloadArg;
    private Handler mHandler = new Handler(Looper.myLooper());

    public UrlDownloadRequest(String taskId, String urlStr, String filePathStr){
        this.taskId = taskId;
        urls = new ArrayList<>();
        filePaths = new ArrayList<>();
        urls.add(urlStr);
        filePaths.add(filePathStr);
        downloadArg = new DownloadArg(this.taskId, this.urls,this.filePaths);
    }

    public UrlDownloadRequest(String taskId,List<String> urls, List<String> filePathStrs){
        this.taskId = taskId;
        this.urls = new ArrayList<>();
        this.filePaths = new ArrayList<>();
        this.urls.addAll(urls);
        this.filePaths.addAll(filePathStrs);
        downloadArg = new DownloadArg(this.taskId, this.urls,this.filePaths);
    }

    public DownloadArg getDownloadArg() {
        return downloadArg;
    }

    /**
     * 下载单个文件
     */
    @SuppressLint("CheckResult")
    public void request(DownloadCallback callback){
        Log.d(TAG, "request url:" + downloadArg.getUrlStr() + " 保存:" + downloadArg.getTargetFileAbsPaths().get(0));
        if(callback != null)
            callback.onDownloadStart(downloadArg);
        Observable.create(new ObservableOnSubscribe<Boolean>() {
                    @Override
                    public void subscribe(ObservableEmitter<Boolean> e) throws Exception {
                        boolean down = doHttpConnection();
                        e.onNext(down);
                    }
                }).subscribeOn(Schedulers.io())

                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        // 结束
                        if (aBoolean) {
                            if(callback != null)
                                callback.onDownloadComplete(downloadArg);
                        } else {
                            if(callback != null)
                                callback.onDownloadError(downloadArg);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private boolean doHttpConnection(){
        Log.d(TAG, "doHttpConnection ");
        HttpURLConnection con = null;
        BufferedInputStream inputStream = null;
        FileOutputStream outputStream = null;
        boolean result = false;

        try {
            URL url = new URL(downloadArg.getUrlStr().get(0));

            if (url.getProtocol().toLowerCase().equals("https")) {
                trustAllHosts();
                HttpsURLConnection https= (HttpsURLConnection) url.openConnection();
                HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

                    @Override
                    public boolean verify(String hostname, SSLSession sslsession) {

                        /*if("qcloudcos.xunjiepdf.com".equals(hostname)){//添加信任https开头的域名
                            return true;
                        } else {
                            return false;
                        }*/
                        return true;
                    }});
                https.setHostnameVerifier(DO_NOT_VERIFY);
                con = https;
            } else {
                con = (HttpURLConnection)url.openConnection();
            }

            if(con.getResponseCode() == HttpURLConnection.HTTP_OK) {

            }

            long contentLength = con.getContentLength();

            // 网络流
            inputStream = new BufferedInputStream(url.openStream());
            // 本地存储文件流
            outputStream = new FileOutputStream(downloadArg.getTargetFileAbsPaths().get(0));

            // 缓存
            byte[] buffer = new byte[1024];
            long total = 0l;
            int count;

            // 获取网络流里所有数据并保存到本地文件库
            do {
                count = inputStream.read(buffer);
                if (count != -1) {
                    total += count;
                    outputStream.write(buffer, 0, count);
                    int progress = (int) (100 * (total / contentLength));
                    Log.d(TAG, "下载文件进度----------->" + progress);

                    // 切换到UI线程
//                    GlobalScope.launch(Dispatchers.Main) {
//                    if(callback != null)
//                        callback?.onDownloadProgress(downloadArg, progress.toInt())
//                    }
                }
            } while (count != -1);
            outputStream.flush();
            inputStream.close();
            result = true;
        }catch (Exception e){
            Log.d(TAG, "下载抛出异常doHttpConnection ----------->" + e.getMessage());
            e.printStackTrace();
            result =  false;
        }finally {
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(con != null){
                con.disconnect();
            }
        }
        return result;
    }

    final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {

        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    /**
     * 信任所有服务器，无需验证证书
     */
    private static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }

            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
        } };

        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 调用下载文件组件DownloadManager（支持断点续传）
     */
    public void downloadFile(FileTranslateCallback fileTranslateCallback){
        final List<String> urls = downloadArg.getUrlStr();
        CountDownLatch countDownLatch = new CountDownLatch(urls.size());
        if(fileTranslateCallback != null){
            mHandler.post(()-> fileTranslateCallback.onDownloadStart(downloadArg));
        }
        for (int i=0;i<urls.size();i++){
            int finalI = i;
            DownloadManager.getInstance().download(urls.get(i), false, new DownLoadObserver() {

                @Override
                public void onError(Throwable e) {
                    countDownLatch.countDown();
                }

                @Override
                public void onComplete(DownloadInfo downloadInfo) {
                    downloadArg.getTargetFileAbsPaths().set(finalI, downloadInfo.getFilePath());
                    countDownLatch.countDown();
                }
            });
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        if(fileTranslateCallback != null){
            mHandler.post(()-> fileTranslateCallback.onDownloadComplete(downloadArg));
        }
    }


    /**下载多个文件*/
    public void downloadFile(DownloadCallback callback){
        final List<String> urls = downloadArg.getUrlStr();
        final long startTime = System.currentTimeMillis();
        CountDownLatch countDownLatch = new CountDownLatch(urls.size());
        if(callback != null){
            mHandler.post(()-> callback.onDownloadStart(downloadArg));
        }
        OkHttpClient okHttpClient = new OkHttpClient();
        for (int i=0;i<urls.size();i++){
            int finalI = i;
            Request request = new Request.Builder().url(urls.get(finalI)).build();
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    countDownLatch.countDown();
                    // 下载失败
                    e.printStackTrace();
                        /*if(callback != null)
                            callback.onDownloadError(downloadArg);*/
                    Log.d(TAG,"download failed");
                }
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    InputStream is = null;
                    FileOutputStream fos = null;
                    // 储存下载文件的目录
                    final String savePath = downloadArg.getTargetFileAbsPaths().get(finalI);
                    try {
                        is = response.body().byteStream();
                        long total = response.body().contentLength();
                        Log.d(TAG,"total = "+total);
                        File file = new File(savePath);
                        fos = new FileOutputStream(file);
                        byte[] buf = new byte[2048];
                        int len = 0;
                        while ((len = is.read(buf)) != -1) {
                            fos.write(buf, 0, len);
                        }
                        fos.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                        Log.d(TAG, "下载抛出异常doHttpConnection ----------->" + e.getMessage());
                    } finally {
                        try {
                            if (is != null)
                                is.close();
                        } catch (IOException e) {
                        }
                        try {
                            if (fos != null)
                                fos.close();
                        } catch (IOException e) {
                        }
                    }
                    countDownLatch.countDown();
                }
            });
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        Log.d(TAG,"download success");
        Log.d(TAG,"totalTime="+ (System.currentTimeMillis() - startTime));
        if(callback != null){
            mHandler.post(()-> callback.onDownloadComplete(downloadArg));
        }
    }



    /**
     * @Description: 下载回调
     */
    public interface DownloadCallback {
        void onDownloadStart(@Nullable DownloadArg downloadArg);
        void onDownloadProgress(@Nullable DownloadArg downloadArg, int progress);
        void onDownloadError(@Nullable DownloadArg downloadArg);
        void onDownloadComplete(@Nullable DownloadArg downloadArg);
    }
}
